from typing import List, Optional
from sqlalchemy.orm import Session
from datetime import datetime, timedelta
from passlib.context import CryptContext
from jose import JWTError, jwt
from ..models.user import User as UserModel
from ..models.department import Department
from ..schemas.user import UserCreate, UserUpdate, PasswordChange, PasswordReset
from fastapi import HTTPException, status

# 密码哈希上下文
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

class UserService:
    def __init__(self, db: Session, secret_key: str, algorithm: str, access_token_expire_minutes: int):
        self.db = db
        self.secret_key = secret_key
        self.algorithm = algorithm
        self.access_token_expire_minutes = access_token_expire_minutes

    def verify_password(self, plain_password: str, hashed_password: str) -> bool:
        """验证密码是否正确"""
        return pwd_context.verify(plain_password, hashed_password)

    def get_password_hash(self, password: str) -> str:
        """生成密码哈希"""
        return pwd_context.hash(password)

    def get_users(self, skip: int = 0, limit: int = 100) -> List[UserModel]:
        """获取用户列表"""
        return self.db.query(UserModel).offset(skip).limit(limit).all()

    def get_user(self, user_id: int) -> Optional[UserModel]:
        """根据ID获取用户"""
        return self.db.query(UserModel).filter(UserModel.id == user_id).first()

    def get_user_by_username(self, username: str) -> Optional[UserModel]:
        """根据用户名获取用户"""
        return self.db.query(UserModel).filter(UserModel.username == username).first()

    def get_user_by_email(self, email: str) -> Optional[UserModel]:
        """根据邮箱获取用户"""
        return self.db.query(UserModel).filter(UserModel.email == email).first()

    def create_user(self, user_data: UserCreate) -> UserModel:
        """创建新用户"""
        # 检查用户名是否已存在
        db_user = self.get_user_by_username(user_data.username)
        if db_user:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="用户名已存在"
            )
        
        # 检查邮箱是否已存在
        db_user = self.get_user_by_email(user_data.email)
        if db_user:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="邮箱已存在"
            )
        
        # 检查部门是否存在（如果指定了部门）
        if user_data.department_id:
            department = self.db.query(Department).filter(Department.id == user_data.department_id).first()
            if not department:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail="部门不存在"
                )
        
        # 创建新用户
        hashed_password = self.get_password_hash(user_data.password)
        db_user = UserModel(
            username=user_data.username,
            email=user_data.email,
            full_name=user_data.full_name,
            department_id=user_data.department_id,
            hashed_password=hashed_password
        )
        
        self.db.add(db_user)
        self.db.commit()
        self.db.refresh(db_user)
        return db_user

    def update_user(self, user_id: int, user_data: UserUpdate) -> UserModel:
        """更新用户信息"""
        db_user = self.get_user(user_id)
        if not db_user:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )
        
        # 检查用户名是否已存在（如果更新了用户名）
        if user_data.username and user_data.username != db_user.username:
            existing_user = self.get_user_by_username(user_data.username)
            if existing_user:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="用户名已存在"
                )
        
        # 检查邮箱是否已存在（如果更新了邮箱）
        if user_data.email and user_data.email != db_user.email:
            existing_user = self.get_user_by_email(user_data.email)
            if existing_user:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="邮箱已存在"
                )
        
        # 检查部门是否存在（如果更新了部门）
        if user_data.department_id is not None and user_data.department_id != db_user.department_id:
            department = self.db.query(Department).filter(Department.id == user_data.department_id).first()
            if not department:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail="部门不存在"
                )
        
        # 更新用户信息
        for key, value in user_data.dict(exclude_unset=True).items():
            setattr(db_user, key, value)
        
        self.db.commit()
        self.db.refresh(db_user)
        return db_user

    def delete_user(self, user_id: int) -> None:
        """删除用户"""
        db_user = self.get_user(user_id)
        if not db_user:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )
        
        self.db.delete(db_user)
        self.db.commit()

    def change_password(self, user_id: int, password_data: PasswordChange) -> UserModel:
        """修改用户密码"""
        db_user = self.get_user(user_id)
        if not db_user:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )
        
        # 验证当前密码是否正确
        if not self.verify_password(password_data.current_password, db_user.hashed_password):
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="当前密码不正确"
            )
        
        # 更新密码
        db_user.hashed_password = self.get_password_hash(password_data.new_password)
        self.db.commit()
        self.db.refresh(db_user)
        return db_user

    def reset_password(self, reset_token: str, password_data: PasswordReset) -> UserModel:
        """重置用户密码（根据重置令牌）"""
        # 这里简化处理，实际应用中需要实现有效的令牌验证逻辑
        # 通常会有一个专门的密码重置令牌表
        
        # 模拟令牌验证（实际应用中应该从数据库或缓存中验证令牌）
        # 这里假设令牌格式为 "user_id:timestamp:signature"
        try:
            # 简单的令牌解析（实际应用中应使用JWT或其他安全机制）
            parts = reset_token.split(":")
            if len(parts) != 3:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="无效的重置令牌"
                )
            
            user_id = int(parts[0])
            db_user = self.get_user(user_id)
            
            if not db_user:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail="用户不存在"
                )
            
            # 更新密码
            db_user.hashed_password = self.get_password_hash(password_data.new_password)
            self.db.commit()
            self.db.refresh(db_user)
            return db_user
        except Exception:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="无效的重置令牌"
            )

    def get_users_by_department(self, department_id: int) -> List[UserModel]:
        """获取指定部门的用户列表"""
        # 检查部门是否存在
        department = self.db.query(Department).filter(Department.id == department_id).first()
        if not department:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="部门不存在"
            )
        
        return self.db.query(UserModel).filter(UserModel.department_id == department_id).all()

    def toggle_user_status(self, user_id: int) -> UserModel:
        """切换用户激活状态"""
        db_user = self.get_user(user_id)
        if not db_user:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )
        
        db_user.is_active = not db_user.is_active
        self.db.commit()
        self.db.refresh(db_user)
        return db_user